package com.sina.shop.config;

import com.sina.shop.event.SinaApplicationEventMulticaster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池调度配置
 */
@Configuration
public class ScheduleConfig {

    //@Resource
    //private Environment env;


    /*
    属性字段说明
    corePoolSize：线程池维护线程的最少数量
    keepAliveSeconds：允许的空闲时间
    maxPoolSize：线程池维护线程的最大数量
    queueCapacity：缓存队列
    rejectedExecutionHandler：对拒绝task的处理策略

    execute(Runable)方法执行过程
    1、如果此时线程池中的数量小于corePoolSize，即使线程池中的线程都处于空闲状态，
       也要创建新的线程来处理被添加的任务。
    2、如果此时线程池中的数量等于 corePoolSize，但是缓冲队列 workQueue未满，
       那么任务被放入缓冲队列。
    3、如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，
       并且线程池中的数量小于maxPoolSize，建新的线程来处理被添加的任务。
    4、如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，
       并且线程池中的数量等于maxPoolSize，那么通过handler所指定的策略来处理此任务。
       也就是：处理任务的优先级为：核心线程corePoolSize、任务队列workQueue、
       最大线程 maximumPoolSize，如果三者都满了，使用handler处理被拒绝的任务。
    5、当线程池中的线程数量大于corePoolSize时，如果某线程空闲时间超过keepAliveTime，
       线程将被终止。这样，线程池可以动态的调整池中的线程数。
    */


    /**
     * 异步线程调用执行器
     * 当事件使用异步的时候，启动一个线程来执行。调用execute方法来执行
     */
    @Bean
    public Executor asyncExecutor() {
        // TODO Backache_TODO 线程池参数待调整
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //线程池维护线程的最少数量  默认为1
        executor.setCorePoolSize(4);
        //线程池维护线程的最大数量
        executor.setMaxPoolSize(9);
        //队列容量 缓冲队列
        executor.setQueueCapacity(50);
        //设置线程的前缀
        executor.setThreadNamePrefix("async-");
        //主线程直接执行该任务，执行完之后尝试添加下一个任务到线程池中，可以有效降低向线程池内添加任务的速度
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();

        return executor;
    }

    /*
     * 异步线程调用执行器  可返回执行结果，Future模式 调用submit方法去执行
     */
    /*@Bean
    public ExecutorService executorService() {
        // IO密集型任务使用此默认配置即可，后续根据项目需求进行调整
        return Executors.newCachedThreadPool();
    }*/

    /**
     * 事件广播器，使用SimpleAsyncTaskExecutor将监听方法异步化
     * 使事件进行异步处理。
     */
    @Primary
    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster sinaApplicationEventMulticaster() {
        SinaApplicationEventMulticaster eventMulticaster = new SinaApplicationEventMulticaster();
        eventMulticaster.setTaskExecutor(asyncExecutor());

        return eventMulticaster;
    }
}
